package mirrormonkey.core.test.listeners;

import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;

import java.util.Arrays;
import java.util.Random;

import mirrormonkey.core.EntityLifecycleListener;
import mirrormonkey.framework.ConnectionInfo;
import mirrormonkey.framework.entity.StaticEntityData;
import mirrormonkey.framework.entity.SyncEntity;
import mirrormonkey.util.IdGenerator;

public class IdGeneratingListener implements EntityLifecycleListener {

	private static final Random r = new Random();

	private static final IdGenerator ids = new IdGenerator();

	private int order;

	private int id;

	public void genId() {
		id = ids.generateAndReserve();
	}

	@Override
	public void entityInitialized(SyncEntity entity,
			ConnectionInfo connectionInfo) {
		genId();
	}

	@Override
	public void entityReplaced(SyncEntity replacedEntity,
			StaticEntityData replacedStaticData, SyncEntity replacingEntity,
			ConnectionInfo connectionInfo) {
		genId();
	}

	@Override
	public void entityReplacing(SyncEntity replacedEntity,
			StaticEntityData replacedStaticData, SyncEntity replacingEntity,
			ConnectionInfo connectionInfo) {
		genId();
	}

	@Override
	public void entityRemoved(SyncEntity entity, ConnectionInfo connectionInfo) {
		genId();
	}

	private static final void swap(int i1, int i2,
			IdGeneratingListener... listeners) {
		IdGeneratingListener l = listeners[i2];
		listeners[i2] = listeners[i1];
		listeners[i1] = l;
	}

	public static IdGeneratingListener[] permutate(
			IdGeneratingListener... listeners) {
		IdGeneratingListener[] l2 = Arrays.copyOf(listeners, listeners.length);
		for (int i = 0; i < listeners.length; i++) {
			swap(i, r.nextInt(listeners.length), l2);
		}
		setOrder(l2);
		return l2;
	}

	private static void setOrder(IdGeneratingListener... listeners) {
		for (int i = 0; i < listeners.length; i++) {
			listeners[i].order = i;
			listeners[i].id = -1;
		}
	}

	public static void assertOrder(IdGeneratingListener... listeners) {
		IdGeneratingListener prev = listeners[0];
		for (int i = 1; i < listeners.length; i++) {
			assertFalse("" + i, listeners[i].id == -1);
			assertTrue("" + i, prev.id < listeners[i].id);
			prev = listeners[i];
		}
	}

	public void assertBefore(IdGeneratingListener other) {
		assertTrue(id < other.id);
	}

	@Override
	public int getSortingOrder() {
		return order;
	}

}
